package server

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net"
	"time"
	"websocket/myHttp"
	_struct "websocket/struct"
)

type client chan<- string // 对外发送消息的通道

var (
	leaving   = make(chan client)
)

func Start() {
	listener, err := net.Listen("tcp", "127.0.0.1:8888")
	if err != nil{
		log.Fatal(err)
	}
	user := make(map[string]string)
	clients := make(map[client]int64)
	for {
		fmt.Println(user)
		conn, err := listener.Accept()
		if err != nil {
			log.Print(err)
			continue
		}
		go handleConn(conn, user, clients)
	}
}

func handleConn(conn net.Conn, user map[string]string,clients map[client]int64) {
	ch := make(chan string) // 对外发送客户消息的通道
	go clientWriter(conn, ch)
	who := conn.RemoteAddr().String()
	var msg _struct.Message
	// 记录当前客户端的时间
	clients[ch] = time.Now().Unix()

	input := bufio.NewReader(conn)
	var sendSmg string
	var Name string
	for {
		massage,err := input.ReadString('\n')
		//fmt.Println("接收的数据:",massage)
		if err != nil {
			if massage == "" {
				break
			}
			panic("错误")
		}
		err = json.Unmarshal([]byte(massage),&msg)

		if err != nil{
			panic("解析错误")
		}
		if msg.SendType == "login" { // 登陆
			Name = msg.Name
			_, ok := user[Name]
			if ok {
				msg.SendType = "occupy"
				msg.Content = Name + "该用户名已经被占用"
				outMsgJson, err := json.Marshal(msg);if err != nil{

				}
				// 只给自己发消息 提示用户名被占用
				io.WriteString(conn, string(outMsgJson)+"\n")
				if err != nil {
					log.Fatal(err)
					continue
				}
				break
			}
			user[Name] = Name
			sendMsg(ch, clients, massage, msg.Content)
			// 开启心跳检测
			go MyHeartbeat(clients, ch, msg, conn, user, Name)
			// 回调接口
			data := map[string]string{
				"send_type": "login",
				"name":      Name,
				"content":   "登陆",
			}
			resp, err := myHttp.SendRequest("http://localhost:8080/v1/notify", data, "POST", nil)
			if err != nil {
				fmt.Println("获取数据错误")
			}
			fmt.Println("获取的结果", string(resp))

			continue
		}else if msg.SendType == "heartbeat"{ // 心跳
			clients[ch] = time.Now().Unix()
			continue
		}else if msg.SendType == "out"{ // 退出
			// 清理掉名字
			delete(user,Name)
			msg.SendType = "out"
			msg.Content = "用户名:【" + Name + "】:" + who + " 下线"
			outMsgJson, err := json.Marshal(msg);if err != nil{

			}
			sendMsg(ch, clients, string(outMsgJson), "out")
			_, ok := clients[ch]
			if ok {
				delete(clients, ch)
				close(ch)
			}
			break
		}else if msg.SendType == "send_msg"{
			sendSmg = msg.Content
			// 退出
			if sendSmg == "quit"{
				// 清理掉名字
				delete(user,Name)
				msg.SendType = "out"
				msg.Content = "用户名:【" + Name + "】:" + who + " 下线"
				outMsgJson, err := json.Marshal(msg);if err != nil{

				}
				sendMsg(ch, clients, string(outMsgJson), "out")
				_, ok := clients[ch]
				if ok {
					delete(clients, ch)
					close(ch)
				}
				break
			}
			sendMsg(ch, clients, massage, sendSmg)
			// 回调接口
			data := map[string]string{
				"send_type": "send_msg",
				"name":      Name,
				"content":   sendSmg,
			}
			resp, err := myHttp.SendRequest("http://localhost:8080/v1/notify", data, "POST", nil)
			if err != nil {
				fmt.Println("获取数据错误")
			}
			fmt.Println("获取的结果", string(resp))
			continue
		}
	}
	// 等待 心跳包的结束
	<- leaving
	data := map[string]string{
		"send_type": "out",
		"name":      Name,
		"content":   "退出",
	}
	resp, err := myHttp.SendRequest("http://localhost:8080/v1/notify", data, "POST", nil)
	if err != nil {
		fmt.Println("获取数据错误")
	}
	fmt.Println("获取的结果", string(resp))
	// 注意：忽略 input.Err() 中可能的错误
	conn.Close()
}

func clientWriter(conn net.Conn, ch <-chan string) {
	for msg := range ch {
		fmt.Fprintln(conn, msg) // 注意：忽略网络层面的错误
	}
}

// 发送消息
func sendMsg(ch chan string,clients map[client]int64,massage string,sendSmg string) {
	// 判断为空
	if sendSmg == ""{
		return
	}
	for cli := range clients {
		//if cli != ch {
			cli <- massage
		//}
	}
}

// 心跳
func MyHeartbeat(clients map[client]int64, ch chan string, msg _struct.Message, conn net.Conn, user map[string]string, name string) {
	var t int64
	t = 10
	for {
		time.Sleep(time.Second * 2)
		myTime := time.Now().Unix()
		_, ok := clients[ch]
		if ok {
			if myTime-clients[ch] > t {
				msg.SendType = "heartbeat"
				msg.Content = name + "超时断开连接"
				outMsgJson, err := json.Marshal(msg)
				if err != nil {
				}
				// 删除用户列表
				delete(user, name)
				delete(clients, ch)

				sendMsg(ch, clients, string(outMsgJson)+"\n", msg.Content)
				leaving <- ch
				break
			}
		}else{
			break
		}
	}
	fmt.Println("结束")
}